package com.erik.ipmonitor.utils;

import com.alibaba.fastjson2.JSONObject;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Stream;

public class FsServletUtils {
    private static final AntPathMatcher ANT_PATH_MATCHER = new AntPathMatcher();

    public FsServletUtils() {
    }

    public static boolean matchEnv(String... envNames) {
        List<String> activeProfiles = SpringContextUtil.getActiveProfiles();
        Stream var10000 = Arrays.stream(envNames);
        Objects.requireNonNull(activeProfiles);
        return var10000.anyMatch(activeProfiles::contains);
    }

    public static HttpServletRequest getRequest() {
        try {
            return ((ServletRequestAttributes)Objects.requireNonNull(getRequestAttributes())).getRequest();
        } catch (Exception var1) {
            return null;
        }
    }

    public static HttpServletResponse getResponse() {
        try {
            return ((ServletRequestAttributes)Objects.requireNonNull(getRequestAttributes())).getResponse();
        } catch (Exception var1) {
            return null;
        }
    }

    public static ServletRequestAttributes getRequestAttributes() {
        try {
            RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
            return (ServletRequestAttributes)attributes;
        } catch (Exception var1) {
            return null;
        }
    }

    public static String getClientIp() {
        return Objects.isNull(getRequest()) ? "" : getClientIp(getRequest(), "");
    }

    public static String getClientIp(HttpServletRequest request, String... otherHeaderNames) {
        String[] headers = new String[]{"X-Original-Forwarded-For", "X-Forwarded-For", "X-Real-IP", "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR"};
        if (ArrayUtils.isNotEmpty(otherHeaderNames)) {
            headers = (String[])ArrayUtils.addAll(headers, otherHeaderNames);
        }

        return getClientIpByHeader(request, headers);
    }

    public static String getClientIpByHeader(HttpServletRequest request, String... headerNames) {
        for(String header : headerNames) {
            String ip = request.getHeader(header);
            if (!StringUtils.isBlank(ip) && !"unknown".equalsIgnoreCase(ip)) {
                return getMultistageReverseProxyIp(ip);
            }
        }

        String ip = request.getRemoteAddr();
        return getMultistageReverseProxyIp(ip);
    }

    private static String getMultistageReverseProxyIp(String ip) {
        if (ip != null && !ip.isBlank() && ip.indexOf(44) > 0) {
            for(String subIp : Arrays.stream(ip.split(",")).map(StringUtils::trim).toList()) {
                if (!StringUtils.isBlank(ip) && !"unknown".equalsIgnoreCase(ip)) {
                    ip = subIp;
                    break;
                }
            }
        }

        if ("127.0.0.1".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip)) {
            try {
                InetAddress localHost = InetAddress.getLocalHost();
                String ipAddress = localHost.getHostAddress();
                if (ipAddress != null && !ipAddress.isBlank()) {
                    ip = ipAddress;
                }
            } catch (UnknownHostException var4) {
            }
        }

        return ip;
    }

    public static String getClientId(HttpServletRequest request) {
        String clientIp = getClientIp(request);
        String ua = getClientAgent(request);
        if (StringUtils.isNotBlank(clientIp)) {
            return clientIp + " | " + ua;
        } else {
            String var10000 = request.getRemoteAddr();
            return var10000 + " | " + ua;
        }
    }

    public static String getClientAgent(HttpServletRequest request) {
        return request == null ? "" : request.getHeader("user-agent");
    }

    public static JSONObject headerToMap(HttpServletRequest request) {
        JSONObject headers = new JSONObject();
        Enumeration<String> headerNames = request.getHeaderNames();

        while(headerNames.hasMoreElements()) {
            String headerName = (String)headerNames.nextElement();
            String headerValue = request.getHeader(headerName);
            headers.put(headerName, headerValue);
        }

        return headers;
    }

    public static boolean isContentType(boolean isAllMatch, boolean isNullAsTrue, String contentType, List<String> mediaTypes) {
        if (mediaTypes == null) {
            return false;
        } else {
            return contentType != null && !contentType.isEmpty() ? mediaTypes.stream().anyMatch((v) -> isContentType(isAllMatch, isNullAsTrue, v, contentType)) : isNullAsTrue;
        }
    }

    public static boolean isContentType(boolean isAllMatch, boolean isNullAsTrue, String contentType, String mediaType) {
        if (contentType != null && !contentType.isEmpty()) {
            if (mediaType != null && !mediaType.isEmpty()) {
                return isAllMatch ? contentType.equals(mediaType) : mediaType.startsWith(contentType);
            } else {
                return false;
            }
        } else {
            return isNullAsTrue;
        }
    }

    public static boolean isIgnorePath(String path, List<String> ignorePaths) {
        if (ignorePaths != null && !ignorePaths.isEmpty()) {
            boolean isAuth = ignorePaths.contains(path);
            if (!isAuth) {
                isAuth = ignorePaths.stream().anyMatch((ur) -> ANT_PATH_MATCHER.match(ur, path));
            }

            return isAuth;
        } else {
            return false;
        }
    }

    public static JSONObject queryParamsToJson(HttpServletRequest request) {
        Map<String, String[]> paramMap = request.getParameterMap();
        JSONObject json = new JSONObject();
        if (paramMap == null) {
            return json;
        } else {
            for(Map.Entry<String, String[]> entry : paramMap.entrySet()) {
                String key = (String)entry.getKey();
                String[] values = (String[])entry.getValue();
                if (values.length > 1) {
                    json.put(key, values);
                } else {
                    json.put(key, values[0]);
                }
            }

            return json;
        }
    }

    public static boolean isJsonRequest(HttpServletRequest request) {
        return isContentType(true, false, request.getContentType(), "application/json");
    }
}
